﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

using FSM.IBll;
using FSM.Web.Models;
using FSM.Web.Models.Fileter;
using FSM.Model;
using Microsoft.Extensions.Configuration;
using Util.Extensions;
using System.IO.Compression;
using System.IO;
using Util.Helper;
using Newtonsoft.Json;

namespace FSM.Web.Controllers
{
    [Authorize]
    public class ShowController : Controller
    {
        #region 模块

        private readonly IConfiguration _configuration;

        private readonly DataResultModel _drm;

        private readonly ITbFileBll _fileBll;

        private readonly ITbFileLogBll _fileLogBll;

        private readonly ITbFilePredeleteBll _preDeleteBll;

        #endregion

        #region 构造函数

        public ShowController(ITbFileBll fileBll,
            IConfiguration configuration,
            ITbFileLogBll fileLogBll,
            ITbFilePredeleteBll preDeleteBll)
        {
            this._drm = new DataResultModel();
            _fileBll = fileBll;
            _fileLogBll = fileLogBll;
            _preDeleteBll = preDeleteBll;
            _configuration = configuration;
        }

        #endregion

        public IActionResult Index()
        {
            return View();
        }

        /// <summary>
        /// 创建文件夹
        /// </summary>
        /// <returns></returns>
        /// <param name="name">文件夹的名称</param>
        /// <param name="upid">上级文件夹的ID</param>
        [HttpPost]
        [ResultExceptionFilter]
        public JsonResult CreateFolder(string name, int upid)
        {
            string userNo = AuthencationHelper.GetLoginUserNo(User);
            ushort level = 0;
            if (upid > 0)
            {
                tb_file folder = _fileBll.Get(upid);
                if (folder == null)
                {
                    throw new Exception($"ERROR({upid}):上级文件夹不存在");
                }
                level = (ushort)(folder.level + 1);
            }
            tb_file entity = new tb_file()
            {
                name = name,
                size = 0,
                type = 1,
                upid = upid,
                level = level,
                dir = userNo,
                creater = userNo,
                create_date = DateTime.Now,
                editer = userNo,
                edit_date = DateTime.Now
            };
            _fileBll.Insert(entity);
            _drm.data = entity;
            _drm.success = true;
            return _drm.ToJson();
        }

        /// <summary>
        /// 重命名文件
        /// </summary>
        /// <param name="id">文件ID</param>
        /// <param name="name">文件新名称</param>
        /// <returns></returns>
        [HttpPost]
        [ResultExceptionFilter]
        public JsonResult Rename(int id, string name)
        {
            name.ValidEmptyThrowException("名称");
            string userNo = AuthencationHelper.GetLoginUserNo(User);
            tb_file entity = _fileBll.Get(id);
            if (entity == null)
            {
                throw new Exception("当前文件或文件夹不存在");
            }
            entity.name = name;
            bool success = _fileBll.UpdateFileName(userNo, id, name);
            if (!success)
            {
                throw new Exception("重命名失败");
            }
            _drm.success = true;
            _drm.data = _fileBll.Get(id);
            return _drm.ToJson();
        }

        /// <summary>
        /// 查询当前文件夹下的所有文件及文件夹信息
        /// </summary>
        /// <param name="name">夹</param>
        /// <param name="upid">上级文件夹ID</param>
        /// <param name="page">页码</param>
        /// <param name="page_size">每页显示的记录数</param>
        /// <returns></returns>
        [HttpPost]
        [ResultExceptionFilter]
        public JsonResult List(string name, int pid, string ordername, int? ordertype, int page, int page_size = 30)
        {
            string userNo = AuthencationHelper.GetLoginUserNo(User);
            var result = _fileBll.ListPagin(userNo, pid, name, null, null, ordername, ordertype, page, page_size);
            _drm.success = true;
            _drm.data = result.Item1;
            return _drm.ToJson();
        }

        /// <summary>
        /// 查询文件/文件夹的操作动态
        /// </summary>
        /// <param name="id">文件/文件夹的ID</param>
        /// <returns></returns>
        [HttpPost]
        [ResultExceptionFilter]
        public JsonResult ListFileLogs(int id)
        {
            List<tb_file_log> logs = _fileLogBll.List(id);
            _drm.success = true;
            _drm.data = logs.OrderByDescending(p=>p.op_date);
            return _drm.ToJson();
        }

        /// <summary>
        /// 上传文件
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [ResultExceptionFilter]
        public JsonResult Upload(int pid)
        {
            ushort level = 0;
            if (pid > 0)
            {
                tb_file folder = _fileBll.Get(pid);
                if (folder == null)
                {
                    throw new Exception($"ERROR({pid}):上级文件夹不存在");
                }
                level = (ushort)(folder.level + 1);
            }

            string userNo = AuthencationHelper.GetLoginUserNo(User);
            var files = Request.Form.Files;
            if (files != null && files.Count > 0)
            {
                foreach (var file in files)
                {
                    tb_file fileEntity = new tb_file()
                    {
                        name = file.FileName,
                        creater = userNo,
                        create_date = DateTime.Now,
                        editer = userNo,
                        edit_date = DateTime.Now,
                        size = file.Length,
                        type = 2,
                        level = level,
                        upid = pid,
                        dir = userNo
                    };
                    bool success = _fileBll.Exists(pid, fileEntity.name);
                    if (success)
                    {
                        throw new Exception($"文件【{fileEntity.name}】已存在");
                    }
                    success = _fileBll.Insert(fileEntity);
                    if (success)
                    {
                        _drm.success = true;
                        _drm.data = fileEntity;
                    }
                    else
                    {
                        throw new Exception("文件记录保存失败");
                    }
                    try
                    {
                        string filePath = _configuration.GetSection("FolderPath").Value;
                        filePath = $"{filePath}\\{fileEntity.dir}";
                        if (!System.IO.Directory.Exists(filePath))
                        {
                            System.IO.Directory.CreateDirectory(filePath);
                        }
                        filePath = $"{filePath}\\{fileEntity.id}";
                        using (var stream = System.IO.File.Create(filePath))
                        {
                            file.CopyToAsync(stream).Wait();
                        }
                    }
                    catch (Exception)
                    {
                        _fileBll.DeleteById(fileEntity.id.Value);
                        throw new Exception("文件保存失败");
                    }
                    break;
                }
            }
            else
            {
                _drm.success = false;
                _drm.message = "上传的文件为空";
            }
            return _drm.ToJson();
        }

        /// <summary>
        /// 下载文件/文件夹
        /// </summary>
        /// <param name="id">文件/文件夹ID</param>
        /// <returns></returns>
        [HttpGet]
        [ResultExceptionFilter]
        public async Task<IActionResult> DownLoad(int id)
        {
            tb_file file = _fileBll.Get(id);
            string basePath = _configuration.GetSection("FolderPath").Value;
            if (file.type == 1)
            {
                byte[] bytes = await _fileBll.CreateZipArchive(basePath, id);
                file.name += ".zip";
                return File(bytes, "application/octet-stream", file.name);
            }
            else
            {
                string absPath = $"{basePath}\\{file.dir}\\{file.id}";
                if (!System.IO.Directory.Exists(absPath))
                {
                    throw new FileNotFoundException("文件不存在，请确认后再试");
                }
                Stream stream = System.IO.File.OpenRead(absPath);
                return File(stream, "application/octet-stream", file.name);
            }
        }

        /// <summary>
        /// 下载所属的文件/文件夹
        /// </summary>
        /// <param name="ids">文件/文件ID 以","分割</param>
        /// <returns></returns>
        [HttpGet]
        public async Task<IActionResult> DownLoads(string ids)
        {
            ids.ValidEmptyThrowException("参数");
            int[] idArr = ids.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(p => Convert.ToInt32(p)).ToArray();
            string basePath = _configuration.GetSection("FolderPath").Value;

            byte[] bytes = await _fileBll.CreateZipArchive(basePath, idArr);
            return File(bytes, "application/octet-stream", "fsm_download.zip");
        }

        /// <summary>
        /// 删除文件或文件夹
        /// </summary>
        /// <param name="id">文件ID</param>
        /// <returns></returns>
        [HttpPost]
        [ResultExceptionFilter]
        public JsonResult Delete(string ids)
        {
            ids.ValidEmptyThrowException("数据不能为空");
            string userNo = AuthencationHelper.GetLoginUserNo(User);
            int[] idArr = ids.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries)
                             .Select(p => Convert.ToInt32(p))
                             .ToArray();
            bool success = _fileBll.DeleteForVirual(userNo, idArr);
            if (!success)
            {
                throw new Exception("删除失败");
            }
            _drm.success = true;
            return _drm.ToJson();
        }

        /// <summary>
        /// 获得已删除的文件或文件夹信息
        /// </summary>
        /// <param name="name">文件/文件夹的名称</param>
        /// <param name="ordername">排序名称</param>
        /// <param name="ordertype">排序类型</param>
        /// <param name="page">页码</param>
        /// <param name="page_size">每页显示的数量</param>
        /// <returns></returns>
        [HttpPost]
        [ResultExceptionFilter]
        public JsonResult ListDeleted(string name, string ordername, int? ordertype, int page = 1, int page_size = 30)
        {
            var list = _preDeleteBll.ListPagin(null, name, null, null, true, ordername, ordertype, page, page_size);
            _drm.success = true;
            _drm.data = list.Item1;
            return _drm.ToJson();
        }

        /// <summary>
        /// 判断要还原的文件是否有重复的
        /// </summary>
        /// <param name="ids">要还原文件ID</param>
        /// <returns></returns>
        [HttpPost]
        [ResultExceptionFilter]
        public JsonResult ExistRepeatFiles(int id)
        {
            List<KeyValuePair<int, string>> list = _fileBll.CheckFilesExists(id);
            _drm.success = true;
            _drm.data = list;
            return _drm.ToJson();
        }

        /// <summary>
        /// 还原已删除的文件/文件夹
        /// </summary>
        /// <param name="ids">文件/文件夹的ID字串，以英文","分割</param>
        /// <param name="dealType">
        /// 用户处理方法
        /// 1、跳过已存在的文件
        /// 2、替换已存在的文件
        /// 3、重命名待还原的文件
        /// 4、自定义每个文件的还原原则
        /// </param>
        /// <param name="selfRestores">单个文件的自定义的还原方式</param>
        /// <returns></returns>
        [HttpPost]
        [ResultExceptionFilter]
        public JsonResult Restore(string ids, UserDealFileTypeEnum dealType, string selfRestores)
        {
            List<PubKeyValue<int, UserDealFileTypeEnum>> userDealTypes = JsonConvert.DeserializeObject<List<PubKeyValue<int, UserDealFileTypeEnum>>>(selfRestores);
            switch (dealType)
            {
                case UserDealFileTypeEnum.Null:
                case UserDealFileTypeEnum.Jump:
                case UserDealFileTypeEnum.Cover:
                case UserDealFileTypeEnum.Rename:
                    userDealTypes.ForEach(x => x.Value = dealType);
                    break;
                case UserDealFileTypeEnum.Self:
                    break;
                default:
                    throw new Exception("请选择冲突处理方法");
            }
            string userNo = AuthencationHelper.GetLoginUserNo(User);
            IEnumerable<int> idList = ids.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries).Select(p => Convert.ToInt32(p));
            bool success = _fileBll.RestoreFiles(userNo, idList, userDealTypes);
            if (!success)
            {
                throw new Exception("还原失败");
            }
            _drm.success = true;
            return _drm.ToJson();
        }

        /// <summary>
        /// 移动目录到指定的文件夹中
        /// </summary>
        /// <param name="moveId">要移动的文件/文件夹ID</param>
        /// <param name="targetId">目标文件夹的ID</param>
        /// <returns>
        /// 移动后返回目标文件夹的信息
        /// </returns>
        [HttpPost]
        [ResultExceptionFilter]
        public JsonResult Move(int? moveId, int? targetId)
        {
            string userNo = AuthencationHelper.GetLoginUserNo(User);
            _drm.success = _fileBll.MoveTo(userNo, moveId.Value, targetId.Value);
            _drm.data = _fileBll.Get(targetId.Value);
            return _drm.ToJson();
        }
    }
}
